package cn.tedu.autoshow.commons.util;

import cn.tedu.autoshow.commons.pojo.po.LoginInfoPO;
import io.jsonwebtoken.*;
import lombok.extern.slf4j.Slf4j;

import java.io.PrintWriter;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;

@Slf4j
public class JwtUtils {

    /**
     * 生成JWT
     * @param loginInfoPO
     * @param secretKey
     * @param tokenDuration
     * @return
     */
    public static String generateToken(LoginInfoPO loginInfoPO, String secretKey, long tokenDuration){
        Map<String, Object> claims = new HashMap<>();
        claims.put("id", loginInfoPO.getId());
        claims.put("username", loginInfoPO.getUsername());
        //claims.put("userType", loginInfoPO.getUserType());
        Date tokenExpiration = new Date(System.currentTimeMillis() + tokenDuration);
        String jwt = Jwts.builder()
                // Header
                .setHeaderParam("alg", "HS256")
                .setHeaderParam("typ", "JWT")
                // Payload
                .setClaims(claims)
                .setExpiration(tokenExpiration)
                // Verify Signature
                .signWith(SignatureAlgorithm.HS256, secretKey)
                // 生成
                .compact();
        return jwt;
    }

    /**
     * 解析JWT为LoginInfoPO对象
     * @param secretKey
     * @param jwt
     * @return
     */
    public static LoginInfoPO getLoginSimpleInfo(String secretKey, String jwt){
        Claims claims = getClaimsFromToken(secretKey, jwt);
        if(claims==null){
            return null;
        }
        Long id = claims.get("id", Long.class);
        String username = claims.get("username", String.class);
        //String userType = claims.get("userType", String.class);

        return new LoginInfoPO().setId(id).setUsername(username);
    }

    /**
     * 解析JWT
     * @param secretKey
     * @param jwt
     * @return
     */
    private static Claims getClaimsFromToken(String secretKey, String jwt) {
        Claims claims = null;
        try {
            claims = Jwts.parser()
                    .setSigningKey(secretKey)
                    .parseClaimsJws(jwt)
                    .getBody();
            log.info("当需要解析Token时，获取载荷");
        } catch (MalformedJwtException e) {
            String message = "非法访问！";
            log.warn("解析JWT时出现MalformedJwtException，将响应错误消息：{}", message);
        } catch (SignatureException e) {
            String message = "非法访问！";
            log.warn("解析JWT时出现SignatureException，将响应错误消息：{}", message);
        } catch (ExpiredJwtException e) {
            String message = "您的登录信息已过期，请重新登录！";
            log.warn("解析JWT时出现ExpiredJwtException，将响应错误消息：{}", message);
        } catch (Throwable e) {
            String message = "服务器忙，请稍后再次尝试！（开发过程中，如果看到此提示，请检查控制台的信息，并补充处理异常的方法）";
            log.warn("解析JWT时出现Throwable，将响应错误消息：{}", message);
            log.warn("异常类型：{}", e.getClass());
            log.warn("异常信息：{}", e.getMessage());
        }
        return claims;
    }
}
